--[[
 * 安全迭代的map，每个实例有两个数据区域_keys:list和_data:map，_keys是map中键的集合，
 * _data是键-值对的集合。
 * 如果遍历会修改map，在遍历开始之前必须调用begin_iter标记脏迭代的开始，并在遍历结束
 * 之后用end_iter通知脏迭代结束。普通的查询型遍历不用这样做。
 * 在脏迭代中，每次迭代的键值从_keys中获取，再从_data中获取相关的值。脏迭代时对map的
 * 修的操作是作用在_data上的，对_keys没有影响，因此不会使迭代失效。脏迭代结束后，用
 * _data的键集合替代_keys 
]]

-- 模块定义
local M = 
{
    _base_class = require "objects.Object",
    _class_name = "collections.MapSafeIter"
};
setmetatable (M, {__index = _G; });
_ENV = M;

-- 引用模块
local Map = require "collections.Map"
local List = require "collections.List"
local Tools = require "tools.CommonTools"

-- 方法定义
operation_table = Tools.CreateOperationTable (_base_class);

-- 字典中的键/值对数目
function operation_table.Count (self)
    return self._data:Count ();
end;

-- 获取字典中和指定的键关联的值，不存在返回nil
function operation_table.GetItem (self, key)
    return self._data:GetItem (key);
end;

-- 设置字典中和指定的键关联的值，不存在时抛出错误
function operation_table.SetItem (self, key, value)
    self._data:SetItem (key, value);
end;

-- 向字典中添加元素
function operation_table.Add (self, key, value)
    if self:_InnerIsIterating () then
        self._data:Add (key, value);
    else
        self._data:Add (key, value);
        self._keys:Add (key);
    end
end;

-- 从字典中清除某项
function operation_table.Rmv (self, key)
    if (self:_InnerIsIterating ()) then
        self._data:Rmv (key);
    else
        self._data:Rmv (key);
        self._keys:Rmv (key);
    end;
end;

-- 清空字典
function operation_table.Clear (self)
    if self:_InnerIsIterating () then
        self._data:Clear ();
    else
        self._data:Clear ();
        self._keys:Clear ();
    end
end;

-- 测试是否包含指定键
function operation_table.ContainsKey (self, key)
    return self._data:ContainsKey (key);
end;

-- 测试是否懈含指定值
function operation_table.ContainsValue (self, value)
    return self._data:ContainsValue (value);
end;

-- 标记脏迭代的开始，如果迭代可能会修改字典，则必须用begin_iter标记
function operation_table.BeginIter (self)
    self._iter_depth = self._iter_depth + 1;
end;

-- 获取迭代体
function operation_table.GetIter (self)
    local index = 0;
    return function (_state)
        if (index >= _state._keys:Count ()) then
            return nil;
        else
            index = index + 1;
            for _index = index, self._keys:Count () do
                local key = _state._keys:GetItemAt (_index);
                local value = _state._data:GetItem (key);
                if (value ~= nil) then
                    index = _index;
                    return key, value;
                end;
            end;
            return nil;
        end;
    end, self
end;

-- 标记脏迭代的结束，和begin_iter的使用必须是匹配的
function operation_table.EndIter (self)
    if (self._iter_dpeth == 0) then 
        return;
    end;

    self._iter_depth = self._iter_depth - 1;
    if (self._iter_depth == 0) then
        self._keys:Clear ();
        for key, value in pairs (self._data._data) do
            self._keys:Add (key);
        end;
    end;
end;

-- 迭代是否正在进行
function operation_table._InnerIsIterating (self)
    return self._iter_depth ~= 0;
end;

-- 字符串格式化
function operation_table.__tostring (self)
    return self._data:__tostring ();
end;

function NewMapSafeIter ()
    local instance = _base_class.NewObject ();
    Tools.PrepareInstance (M, instance);

    instance._keys = List.NewList ();
    instance._data = Map.NewMap ();
    instance._iter_depth = 0;

    return instance;
end;

return M;
